<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.1.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon.ico">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">

<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic|JetBrains Mono:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext">
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"www.jnxss.top","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":true,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="课程内容介绍视频地址：https:&#x2F;&#x2F;www.bilibili.com&#x2F;video&#x2F;BV1Vf4y127N5">
<meta property="og:type" content="article">
<meta property="og:title" content="Spring 5 笔记">
<meta property="og:url" content="http://www.jnxss.top/2021/01/28/Spring-5-%E7%AC%94%E8%AE%B0/index.html">
<meta property="og:site_name" content="江南笑书生">
<meta property="og:description" content="课程内容介绍视频地址：https:&#x2F;&#x2F;www.bilibili.com&#x2F;video&#x2F;BV1Vf4y127N5">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/IoC%E5%8E%9F%E7%90%86.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/BeanFactory%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BF%E6%A0%91.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/JDK%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/CGLIB%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/newProxyInstance%E6%96%B9%E6%B3%95.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/newProxyInstance%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/InvocationHandler%E6%8E%A5%E5%8F%A3.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/InvocationHandler.invoke%E6%96%B9%E6%B3%95.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/AOP%E4%BE%9D%E8%B5%96%E5%9B%BE.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/JdbcTemplate%E4%BE%9D%E8%B5%96%E5%9B%BE.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/%E4%BA%8B%E5%8A%A1%E4%BE%9D%E8%B5%96%E5%9B%BE.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/PlatformTransactionManager%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BF%E6%A0%91.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/Spring%205%20%E6%A8%A1%E5%9D%97%E5%9B%BE.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/SpringMVC%E5%AF%B9%E6%AF%94WebFlux.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/Java8%E5%8F%8A%E4%B9%8B%E5%89%8D%E5%93%8D%E5%BA%94%E5%BC%8F.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/map%E6%93%8D%E4%BD%9C%E7%AC%A6%E7%A4%BA%E6%84%8F%E5%9B%BE.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/flatMap%E6%93%8D%E4%BD%9C%E7%AC%A6%E7%A4%BA%E6%84%8F%E5%9B%BE.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/BIO%E7%9A%84%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/NIO%E7%9A%84%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/WebHandler%E6%8E%A5%E5%8F%A3.png">
<meta property="og:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/DispatcherHandler.handle%E6%96%B9%E6%B3%95.png">
<meta property="article:published_time" content="2021-01-28T08:33:57.000Z">
<meta property="article:modified_time" content="2021-05-05T06:19:08.506Z">
<meta property="article:author" content="江南笑书生">
<meta property="article:tag" content="Spring">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/IoC%E5%8E%9F%E7%90%86.png">

<link rel="canonical" href="http://www.jnxss.top/2021/01/28/Spring-5-%E7%AC%94%E8%AE%B0/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Spring 5 笔记 | 江南笑书生</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">江南笑书生</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">殷贵庆的个人博客</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-commonweal">

    <a href="/404/" rel="section"><i class="fa fa-heartbeat fa-fw"></i>公益 404</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container"></div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="algolia-results">
  <div id="algolia-stats"></div>
  <div id="algolia-hits"></div>
  <div id="algolia-pagination" class="algolia-pagination"></div>
</div>

      
    </div>
  </div>

</div>
    </header>

    
  <div class="reading-progress-bar"></div>

  <a href="https://github.com/5ME" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://www.jnxss.top/2021/01/28/Spring-5-%E7%AC%94%E8%AE%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/my-avatar.png">
      <meta itemprop="name" content="江南笑书生">
      <meta itemprop="description" content="心怀梦想，永远奋斗">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="江南笑书生">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Spring 5 笔记
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-01-28 16:33:57" itemprop="dateCreated datePublished" datetime="2021-01-28T16:33:57+08:00">2021-01-28</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-05-05 14:19:08" itemprop="dateModified" datetime="2021-05-05T14:19:08+08:00">2021-05-05</time>
              </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span><br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>45k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>41 分钟</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="课程内容介绍"><a href="#课程内容介绍" class="headerlink" title="课程内容介绍"></a>课程内容介绍</h1><p>视频地址：<a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1Vf4y127N5">https://www.bilibili.com/video/BV1Vf4y127N5</a></p>
<span id="more"></span>

<ol>
<li><p>Spring 概念</p>
</li>
<li><p>IoC 容器</p>
<ol>
<li><p>IoC 底层原理</p>
</li>
<li><p>IoC 接口（BeanFactory）</p>
</li>
<li><p>IoC 操作 Bean 管理（基于xml）</p>
</li>
<li><p>IoC 操作 Bean 管理（基于注解）</p>
</li>
</ol>
</li>
<li><p>AOP</p>
</li>
<li><p>JdbcTemplate</p>
</li>
<li><p>事务管理</p>
</li>
<li><p>Spring 5 新特性</p>
</li>
</ol>
<h1 id="Spring-框架概述"><a href="#Spring-框架概述" class="headerlink" title="Spring 框架概述"></a>Spring 框架概述</h1><ol>
<li><p>Spring 是轻量级的开源的 JavaEE 框架</p>
</li>
<li><p>Spring 可以解决企业应用开发的复杂性</p>
</li>
<li><p>两个核心部分：IoC、AOP</p>
<ul>
<li>IoC：Inversion of Control，控制反转。把创建对象过程交给 Spring 进行管理</li>
<li>AOP：Aspect Oriented Programming，面向切面编程。不修改源代码进行功能增强</li>
</ul>
</li>
<li><p>Spring 特点</p>
<ol>
<li>方便解耦，简化开发</li>
<li>AOP 编程支持</li>
<li>方便程序测试</li>
<li>方便和其他框架进行整合</li>
<li>方便进行事务操作</li>
<li>降低 API 开发难度</li>
</ol>
</li>
<li><p>本课程选取 Spring 5.x</p>
</li>
</ol>
<h1 id="IoC"><a href="#IoC" class="headerlink" title="IoC"></a>IoC</h1><h2 id="概念和原理"><a href="#概念和原理" class="headerlink" title="概念和原理"></a>概念和原理</h2><p>1、什么是 IoC ？</p>
<p>控制反转，把对象创建和对象之间的调用过程，交给 Spring 进行管理</p>
<p>使用 IoC 目的：降低耦合度</p>
<p>入门案例就是 IoC 实现</p>
<p>2、IoC 底层原理</p>
<p>xml 解析、工厂模式、反射</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/IoC%E5%8E%9F%E7%90%86.png" alt="IoC 原理"></p>
<h2 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h2><p>1、IoC 思想基于 IoC 容器完成，IoC 容器底层就是对象工厂</p>
<p>2、Spring 提供 IoC 容器实现两种方式（两个接口）：</p>
<p>（1） <code>BeanFactory</code> ：IoC 容器基本实现，是 Spring 内部使用接口，一般不提供开发人员使用</p>
<p>加载配置文件时不会创建对象，在获取（使用）对象时才创建</p>
<p>（2） <code>ApplicationContext</code> ： <code>BeanFactory</code> 接口的子接口，提供更多更强大的功能，一般由开发人员使用</p>
<p>加载配置文件时就会将配置的对象创建</p>
<p>3、 <code>ApplicationContext</code> 接口有实现类</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/BeanFactory%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BF%E6%A0%91.png" alt="BeanFactory 接口继承树"></p>
<h2 id="IoC-操作-Bean-管理"><a href="#IoC-操作-Bean-管理" class="headerlink" title="IoC 操作 Bean 管理"></a>IoC 操作 Bean 管理</h2><p>1、什么是 Bean 管理</p>
<p>Bean 管理指的是两个操作：Spring 创建对象，Spring 注入属性</p>
<p>2、Bean 管理操作有两种方式</p>
<ul>
<li><p>基于 xml 配置文件方式实现</p>
</li>
<li><p>基于注解方式实现</p>
</li>
</ul>
<h3 id="基于-xml-方式"><a href="#基于-xml-方式" class="headerlink" title="基于 xml 方式"></a>基于 xml 方式</h3><h4 id="基于-xml-方式创建对象"><a href="#基于-xml-方式创建对象" class="headerlink" title="基于 xml 方式创建对象"></a>基于 xml 方式创建对象</h4><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;alice&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<ol>
<li><p>在 Spring 配置文件中，使用 bean 标签，标签中添加对应属性，就可以实现对象创建</p>
</li>
<li><p>bean 标签有很多属性，常用属性：</p>
<ul>
<li><code>id</code>：唯一标识</li>
<li><code>class</code>：全类名</li>
</ul>
</li>
<li><p>创建对象的时候，默认执行无参构造器</p>
</li>
</ol>
<h4 id="基于-xml-方式注入属性"><a href="#基于-xml-方式注入属性" class="headerlink" title="基于 xml 方式注入属性"></a>基于 xml 方式注入属性</h4><p>DI：Dependency Injection，依赖注入，是 IoC 的一种实现方式</p>
<ol>
<li><p><strong>第一种注入方式：set 方法注入</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--set 方法注入--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;alice&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Alice&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;20&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>第二种注入方式：有参构造器注入</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--有参构造器注入--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;bob&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Bob&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">constructor-arg</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;20&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>p 名称空间注入（了解即可）</p>
<p>添加约束：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xmlns:p=&quot;http://www.springframework.org/schema/p&quot;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--p命名空间--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;cindy&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span> <span class="attr">p:name</span>=<span class="string">&quot;Cindy&quot;</span> <span class="attr">p:age</span>=<span class="string">&quot;18&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>c 名称空间注入（了解即可）</p>
<p>添加约束：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xmlns:c=&quot;http://www.springframework.org/schema/c&quot;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--c命名空间--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;david&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span> <span class="attr">c:name</span>=<span class="string">&quot;David&quot;</span> <span class="attr">c:age</span>=<span class="string">&quot;18&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ol>
<h5 id="xml-注入其他类型"><a href="#xml-注入其他类型" class="headerlink" title="xml 注入其他类型"></a>xml 注入其他类型</h5><ol>
<li><p>字面量</p>
<ul>
<li><p>注入 <code>null</code> </p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--注入null--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;eva&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Eva&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">null</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>属性值包含特殊字符</p>
<ul>
<li><p>将特殊字符进行转义</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--属性值包含特殊字符--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;special&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--将特殊字符进行转义--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;<span class="symbol">&amp;lt;</span><span class="symbol">&amp;lt;</span>TRUMP<span class="symbol">&amp;gt;</span><span class="symbol">&amp;gt;</span>&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;18&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：<code>User&#123;name=&#39;&lt;&lt;TRUMP&gt;&gt;&#39;, age=18&#125;</code> </p>
</li>
<li><p>使用 CDATA</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--属性值包含特殊字符--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;special&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--使用 CDATA--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>&lt;![CDATA[&lt;&lt;BIDEN&gt;&gt;]]&gt;<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;18&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：<code>User&#123;name=&#39;&lt;&lt;BIDEN&gt;&gt;&#39;, age=18&#125;</code></p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>外部 bean</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDao</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">delete</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserDao#delete()...&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    UserDao dao;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setDao</span><span class="params">(UserDao dao)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.dao = dao;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">deleteUser</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserService#deleteUser()...&quot;</span>);</span><br><span class="line">        dao.delete();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userDao&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.dao.UserDao&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;userService&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.service.UserService&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--注入外部 bean--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dao&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;userDao&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>内部 bean</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Department</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String departName;</span><br><span class="line">    <span class="comment">// getter setter toString 等方法在此省略</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Employee</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String empName;</span><br><span class="line">    <span class="keyword">private</span> String email;</span><br><span class="line">    <span class="keyword">private</span> Department dept;</span><br><span class="line">    <span class="comment">// getter setter toString 等方法在此省略</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;employee&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Employee&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;empName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;杰克&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;email&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jack@jack.com&quot;</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--内部 bean--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dept&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">bean</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Department&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;departName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;开发部&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：<code>Employee&#123;empName=&#39;杰克&#39;, email=&#39;jack@jack.com&#39;, dept=Department&#123;departName=&#39;开发部&#39;&#125;&#125;</code> </p>
</li>
<li><p>级联赋值</p>
<p>写法一：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;employee2&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Employee&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;empName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Pony&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;email&quot;</span> <span class="attr">value</span>=<span class="string">&quot;pony@pony.com&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dept&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;department&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;department&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Department&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;departName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;运维部&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：<code>Employee&#123;empName=&#39;Pony&#39;, email=&#39;pony@pony.com&#39;, dept=Department&#123;departName=&#39;运维部&#39;&#125;&#125;</code> </p>
<p>写法二：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;employee2&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Employee&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;empName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Pony&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;email&quot;</span> <span class="attr">value</span>=<span class="string">&quot;pony@pony.com&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dept&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;department&quot;</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--注意这里--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dept.departName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;开发部&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;department&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Department&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;departName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;运维部&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：<code>Employee&#123;empName=&#39;Pony&#39;, email=&#39;pony@pony.com&#39;, dept=Department&#123;departName=&#39;开发部&#39;&#125;&#125;</code></p>
</li>
</ol>
<h5 id="xml-注入集合属性"><a href="#xml-注入集合属性" class="headerlink" title="xml 注入集合属性"></a>xml 注入集合属性</h5><ol>
<li><p><strong>注入数组类型属性</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--数组类型注入--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;array&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">array</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>array1<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>array2<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>array3<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">array</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>注入 List 集合类型属性</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--List 类型注入--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;list&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">list</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>list1<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>list2<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>list3<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>注入 Map 集合类型属性</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--Map 类型注入--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;map&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">map</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;key1&quot;</span> <span class="attr">value</span>=<span class="string">&quot;value1&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;key2&quot;</span> <span class="attr">value</span>=<span class="string">&quot;value2&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">entry</span> <span class="attr">key</span>=<span class="string">&quot;key3&quot;</span> <span class="attr">value</span>=<span class="string">&quot;value3&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">map</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>注入 Set 集合类型属性</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--Set 类型注入--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;set&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">set</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>set1<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>set2<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">value</span>&gt;</span>set3<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">set</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Student&#123;<span class="attribute">stuName</span>=<span class="string">&#x27;Pony&#x27;</span>, array=[array1, array2, array3], list=[list1, list2, list3], map=&#123;<span class="attribute">key1</span>=value1, <span class="attribute">key2</span>=value2, <span class="attribute">key3</span>=value3&#125;, set=[set1, set2, set3]&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>在集合里面设置对象类型</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;student&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Student&quot;</span>&gt;</span></span><br><span class="line">	<span class="comment">&lt;!--省略部分代码，只看有关的--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--在集合里面设置对象类型--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;courses&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">list</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">ref</span> <span class="attr">bean</span>=<span class="string">&quot;course1&quot;</span>/&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">ref</span> <span class="attr">bean</span>=<span class="string">&quot;course2&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">property</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;course1&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Course&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;courseName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;数据结构&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;credit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;5&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;course2&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Course&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;courseName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;操作系统&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;credit&quot;</span> <span class="attr">value</span>=<span class="string">&quot;4&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Course&#123;<span class="attribute">courseName</span>=<span class="string">&#x27;数据结构&#x27;</span>, <span class="attribute">credit</span>=5&#125;, Course&#123;<span class="attribute">courseName</span>=<span class="string">&#x27;操作系统&#x27;</span>, <span class="attribute">credit</span>=4&#125;]</span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>把集合注入部分提取出来</strong></p>
<p>a. 在配置文件中引入 <code>util</code> 名称空间</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:util</span>=<span class="string">&quot;http://www.springframework.org/schema/util&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd&quot;</span>&gt;</span></span><br><span class="line">    </span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>b. 使用 <code>util</code> 标签完成 List 集合注入提取</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Book</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;String&gt; list;</span><br><span class="line">    <span class="comment">// getter setter toString 等方法在此省略</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;book&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Book&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;list&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;bookList&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--List 集合注入提取--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">util:list</span> <span class="attr">id</span>=<span class="string">&quot;bookList&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">value</span>&gt;</span>Java编程思想<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">value</span>&gt;</span>算法导论<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">value</span>&gt;</span>Effective Java<span class="tag">&lt;/<span class="name">value</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">util:list</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">[Java编程思想, 算法导论, Effective Java]</span></span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="FactoryBean"><a href="#FactoryBean" class="headerlink" title="FactoryBean"></a>FactoryBean</h3><p>普通 bean：配置文件中定义的 bean 类型就是返回类型</p>
<p>工厂 bean：配置文件中定义的 bean 类型可以和返回类型不一样</p>
<ol>
<li>创建类，实现 <code>FactoryBean</code> 接口</li>
<li>实现接口的方法</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * MyFactoryBean 工厂Bean</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyFactoryBean</span> <span class="keyword">implements</span> <span class="title class_">FactoryBean</span>&lt;Course&gt; &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Course <span class="title function_">getObject</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Course</span>();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Class&lt;?&gt; getObjectType() &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isSingleton</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;myFactoryBean&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.MyFactoryBean&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test3</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">ioc</span> <span class="operator">=</span></span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring3.xml&quot;</span>);</span><br><span class="line">    <span class="type">Course</span> <span class="variable">course</span> <span class="operator">=</span> ioc.getBean(<span class="string">&quot;myFactoryBean&quot;</span>, Course.class);</span><br><span class="line">    course.setCourseName(<span class="string">&quot;数据结构&quot;</span>);</span><br><span class="line">    course.setCredit(<span class="number">5</span>);</span><br><span class="line">    System.out.println(course);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>测试：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Course&#123;<span class="attribute">courseName</span>=<span class="string">&#x27;数据结构&#x27;</span>, <span class="attribute">credit</span>=5&#125;</span><br></pre></td></tr></table></figure>



<h3 id="Bean-作用域"><a href="#Bean-作用域" class="headerlink" title="Bean 作用域"></a>Bean 作用域</h3><p>在 Spring 中，设置创建 bean 实例是单实例还是多实例（<em><strong>默认单实例</strong></em>）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test4</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">ioc</span> <span class="operator">=</span></span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring2.xml&quot;</span>);</span><br><span class="line">    <span class="type">Book</span> <span class="variable">book1</span> <span class="operator">=</span> ioc.getBean(<span class="string">&quot;book&quot;</span>, Book.class);</span><br><span class="line">    <span class="type">Book</span> <span class="variable">book2</span> <span class="operator">=</span> ioc.getBean(<span class="string">&quot;book&quot;</span>, Book.class);</span><br><span class="line">    <span class="comment">// 这里打印对象地址，需要把其 toString() 方法注释掉</span></span><br><span class="line">    System.out.println(book1);</span><br><span class="line">    System.out.println(book2);</span><br><span class="line">    System.out.println(book1==book2);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">com<span class="selector-class">.yin</span><span class="selector-class">.spring5</span><span class="selector-class">.bean</span>.Book@<span class="number">433</span>defed</span><br><span class="line">com<span class="selector-class">.yin</span><span class="selector-class">.spring5</span><span class="selector-class">.bean</span>.Book@<span class="number">433</span>defed</span><br><span class="line">true</span><br></pre></td></tr></table></figure>

<p>如何设置单实例&#x2F;多实例？<strong>bean 标签中 <code>scope</code> 属性设置作用域</strong></p>
<p><code>scope</code> 属性值：</p>
<ul>
<li><code>singleton</code> ：单实例</li>
<li><code>prototype</code> ：多实例</li>
</ul>
<p>将 scope 属性值设置为 &#96;&#96; 后，再进行上面测试：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;book&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.Book&quot;</span> <span class="attr">scope</span>=<span class="string">&quot;prototype&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">com<span class="selector-class">.yin</span><span class="selector-class">.spring5</span><span class="selector-class">.bean</span>.Book@<span class="number">548</span>a24a</span><br><span class="line">com<span class="selector-class">.yin</span><span class="selector-class">.spring5</span><span class="selector-class">.bean</span>.Book@<span class="number">433</span>defed</span><br><span class="line">false</span><br></pre></td></tr></table></figure>

<p><code>singleton</code> 和 <code>prototype</code> 的区别：</p>
<ol>
<li><p><code>singleton</code> 是单实例，<code>prototype</code> 是多实例</p>
</li>
<li><p><code>singleton</code> 在 Spring 加载配置文件时就会创建单实例对象</p>
<p><code>prototype</code> 在获取对象时才会进行创建</p>
</li>
</ol>
<h3 id="Bean-生命周期"><a href="#Bean-生命周期" class="headerlink" title="Bean 生命周期"></a>Bean 生命周期</h3><p>生命周期：从对象创建到销毁的过程</p>
<p>bean 生命周期：</p>
<ol>
<li>通过构造器创建 bean 实例（无参构造）</li>
<li>为 bean 注入属性和对其他 bean 的引用（set 方法）</li>
<li>调用 bean 的初始化方法（需要进行配置初始化方法）</li>
<li>获取并使用 bean</li>
<li>当容器关闭时，调用 bean 的销毁方法（需要进行配置销毁方法）</li>
</ol>
<p>代码验证：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> Character gender;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">User</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;User 无参构造器执行。。。&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">getName</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setName</span><span class="params">(String name)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;User.setName 执行。。。&quot;</span>);</span><br><span class="line">        <span class="built_in">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">getAge</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setAge</span><span class="params">(Integer age)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;User.setAge 执行。。。&quot;</span>);</span><br><span class="line">        <span class="built_in">this</span>.age = age;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Character <span class="title function_">getGender</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> gender;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setGender</span><span class="params">(Character gender)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;User.setGender 执行。。。&quot;</span>);</span><br><span class="line">        <span class="built_in">this</span>.gender = gender;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;自定义 User.init 执行。。。&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">destroy</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;自定义 User.destroy 执行。。。&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;user&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.User&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">init-method</span>=<span class="string">&quot;init&quot;</span> <span class="attr">destroy-method</span>=<span class="string">&quot;destroy&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;name&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Alice&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;gender&quot;</span> <span class="attr">value</span>=<span class="string">&quot;F&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span> <span class="attr">value</span>=<span class="string">&quot;20&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test5</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ClassPathXmlApplicationContext</span> <span class="variable">ioc</span> <span class="operator">=</span></span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring4.xml&quot;</span>);</span><br><span class="line">    <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> ioc.getBean(<span class="string">&quot;user&quot;</span>, User.class);</span><br><span class="line">    System.out.println(user);</span><br><span class="line">    <span class="comment">// 关闭容器</span></span><br><span class="line">    ioc.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">User 无参构造器执行。。。</span><br><span class="line">User<span class="selector-class">.setName</span> 执行。。。</span><br><span class="line">User<span class="selector-class">.setGender</span> 执行。。。</span><br><span class="line">User<span class="selector-class">.setAge</span> 执行。。。</span><br><span class="line">自定义 User<span class="selector-class">.init</span> 执行。。。</span><br><span class="line">com<span class="selector-class">.yin</span><span class="selector-class">.spring5</span><span class="selector-class">.bean</span>.User@<span class="number">16</span>eb3ea3</span><br><span class="line">自定义 User<span class="selector-class">.destroy</span> 执行。。。</span><br></pre></td></tr></table></figure>

<p>其实完整来讲，bean 的声明周期有 7 步。在初始化方法执行前后，分别有 <code>postProcessBeforeInitialization</code> 和 <code>postProcessAfterInitialization</code> 方法执行。</p>
<p>在上述代码的基础上，再添加以下内容：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MyBeanPost</span> <span class="keyword">implements</span> <span class="title class_">BeanPostProcessor</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">postProcessBeforeInitialization</span><span class="params">(Object bean,</span></span><br><span class="line"><span class="params">                                                  String beanName)</span> <span class="keyword">throws</span> BeansException &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;    postProcessBeforeInitialization 执行。。。&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">postProcessAfterInitialization</span><span class="params">(Object bean,</span></span><br><span class="line"><span class="params">                                                 String beanName)</span> <span class="keyword">throws</span> BeansException &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;    postProcessAfterInitialization 执行。。。&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;myBeanPost&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.bean.MyBeanPost&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>再次进行测试，输出如下：</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">User 无参构造器执行。。。</span><br><span class="line">User<span class="selector-class">.setName</span> 执行。。。</span><br><span class="line">User<span class="selector-class">.setGender</span> 执行。。。</span><br><span class="line">User<span class="selector-class">.setAge</span> 执行。。。</span><br><span class="line">    postProcessBeforeInitialization 执行。。。</span><br><span class="line">自定义 User<span class="selector-class">.init</span> 执行。。。</span><br><span class="line">    postProcessAfterInitialization 执行。。。</span><br><span class="line">com<span class="selector-class">.yin</span><span class="selector-class">.spring5</span><span class="selector-class">.bean</span>.User@<span class="number">33</span>bc72d1</span><br><span class="line">自定义 User<span class="selector-class">.destroy</span> 执行。。。</span><br></pre></td></tr></table></figure>

<p>综上，bean 生命周期完整表述如下：</p>
<ol>
<li>通过构造器创建 bean 实例（无参构造）</li>
<li>为 bean 注入属性和对其他 bean 的引用（set 方法）</li>
<li>把 bean 实例传递给初始化前的后置处理 <code>postProcessBeforeInitialization</code> </li>
<li>调用 bean 的初始化方法（需要进行配置初始化方法）</li>
<li>把 bean 实例传递给初始化后的后置处理 <code>postProcessAfterInitialization</code></li>
<li>获取并使用 bean</li>
<li>当容器关闭时，调用 bean 的销毁方法（需要进行配置销毁方法）</li>
</ol>
<h3 id="xml-自动装配"><a href="#xml-自动装配" class="headerlink" title="xml 自动装配"></a>xml 自动装配</h3><p>什么是自动装配？</p>
<p>根据指定装配规则（属性名称或属性类型），Spring 自动将匹配的属性值进行注入</p>
<p>bean 标签中的 <code>autowire</code> 属性可以配置自动装配，<code>autowire</code> 常用属性值：</p>
<ul>
<li><code>byName</code> ：根据名称装配（<em><strong>注入 bean 的 id 要与被注入 bean 的 set 方法一致</strong></em>）</li>
<li><code>byType</code> ：根据类型装配（有多个同类型的 bean 时，此属性值无法使用）</li>
</ul>
<p>代码演示：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Department</span> &#123;</span><br><span class="line">    <span class="comment">// 此处略去 get set toString 等方法</span></span><br><span class="line">    <span class="keyword">private</span> String deptName;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Employee</span> &#123;</span><br><span class="line">    <span class="comment">// 此处略去 get set toString 等方法</span></span><br><span class="line">    <span class="keyword">private</span> String empName;</span><br><span class="line">    <span class="keyword">private</span> Department dept;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dept&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.autowire.Department&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;deptName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;开发部&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dept2&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.autowire.Department&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;deptName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;测试部&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;emp&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.yin.spring5.autowire.Employee&quot;</span> <span class="attr">autowire</span>=<span class="string">&quot;byName&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;empName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;Pony&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Employee&#123;<span class="attribute">empName</span>=<span class="string">&#x27;Pony&#x27;</span>, <span class="attribute">dept</span>=Department&#123;<span class="attribute">deptName</span>=<span class="string">&#x27;开发部&#x27;</span>&#125;&#125;</span><br></pre></td></tr></table></figure>

<p>若将 <code>Employee</code> 类中默认生成的 <code>setDept</code> 方法名修改为 <code>setDept2</code>，则输出变为：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Employee&#123;<span class="attribute">empName</span>=<span class="string">&#x27;Pony&#x27;</span>, <span class="attribute">dept</span>=Department&#123;<span class="attribute">deptName</span>=<span class="string">&#x27;测试部&#x27;</span>&#125;&#125;</span><br></pre></td></tr></table></figure>

<p>由此证实：**<code>byName</code> 的自动注入是根据 set 方法判断的，而不是类中的属性名**。</p>
<h3 id="外部属性文件"><a href="#外部属性文件" class="headerlink" title="外部属性文件"></a>外部属性文件</h3><p>以数据库连接池为例：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.alibaba.druid.pool.DruidDataSource&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClassName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.mysql.cj.jdbc.Driver&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jdbc:mysql://localhost:3306/jdbc_template?serverTimezone=Asia/Shanghai&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;123456&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>将数据库配置抽取到 properties 文件</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">jdbc.driver</span>=<span class="string">com.mysql.cj.jdbc.Driver</span></span><br><span class="line"><span class="attr">jdbc.url</span>=<span class="string">jdbc:mysql://localhost:3306/jdbc_template?serverTimezone=Asia/Shanghai</span></span><br><span class="line"><span class="attr">jdbc.username</span>=<span class="string">root</span></span><br><span class="line"><span class="attr">jdbc.password</span>=<span class="string">123456</span></span><br></pre></td></tr></table></figure>

<p>则 Spring 配置文件改写如下，注意需要<strong>引入 context 名称空间</strong>：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">&quot;http://www.springframework.org/schema/beans&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">&quot;http://www.springframework.org/schema/context&quot;</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="string"><span class="tag">            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--引入外部 properties 文件--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:property-placeholder</span> <span class="attr">location</span>=<span class="string">&quot;classpath:db-config.properties&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.alibaba.druid.pool.DruidDataSource&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--取出 properties 文件中的值--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClassName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.driver&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.url&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.username&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h3 id="基于注解方式"><a href="#基于注解方式" class="headerlink" title="基于注解方式"></a>基于注解方式</h3><h4 id="创建-bean"><a href="#创建-bean" class="headerlink" title="创建 bean"></a>创建 bean</h4><p>Spring 创建 bean 的四个注解：<code>@Component</code>，<code>@Controller</code>，<code>@Service</code>，<code>@Repository</code>。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--开启组件扫描，将会扫描 base-package 及其子包下所有组件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.yin.spring5&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>排除某些组件，以排除 <code>@Controller</code> 组件扫描为例：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--开启组件扫描--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.yin.spring5&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--排除 Controller 组件扫描--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:exclude-filter</span> <span class="attr">type</span>=<span class="string">&quot;annotation&quot;</span></span></span><br><span class="line"><span class="tag">                            <span class="attr">expression</span>=<span class="string">&quot;org.springframework.stereotype.Controller&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">context:component-scan</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><code>context:component-scan</code> 标签部分属性：</p>
<ul>
<li><code>base-package</code> ：要扫描组件的基础包，默认将会扫描 base-package 及其子包下所有组件</li>
<li><code>use-default-filters</code> ：是否使用默认的扫描规则</li>
</ul>
<p><code>context:component-scan</code> 标签的子标签：</p>
<ul>
<li><code>context:exclude-filter</code> ：指定排除规则</li>
<li><code>context:include-filter</code> ：指定包含规则</li>
</ul>
<h4 id="属性注入"><a href="#属性注入" class="headerlink" title="属性注入"></a>属性注入</h4><ul>
<li><code>@Autowired</code> ：根据属性类型自动装配</li>
<li><code>@Qualifier</code> ：根据属性名称注入</li>
<li><code>@Resource</code> ：可以根据类型注入，可以根据名称注入（这是 javax 包下的注解，已移除）</li>
<li><code>@Value</code> ：注入普通类型属性</li>
</ul>
<hr>
<h1 id="AOP"><a href="#AOP" class="headerlink" title="AOP"></a>AOP</h1><p>AOP，Aspect Oriented Programming，面向切面编程</p>
<p>利用 AOP 可以对业务逻辑的各个部分进行隔离，从而使得业务逻辑各部分之间的<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E8%80%A6%E5%90%88%E5%BA%A6/2603938">耦合度</a>降低，提高程序的可重用性，同时提高了开发的效率。</p>
<h2 id="底层原理"><a href="#底层原理" class="headerlink" title="底层原理"></a>底层原理</h2><p>AOP 底层使用<strong>动态代理</strong>。有两种情况：</p>
<ul>
<li><p>有接口，使用 JDK 动态代理</p>
<p>创建接口实现类代理对象，增强类的方法</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/JDK%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86.png" alt="JDK动态代理"></p>
</li>
<li><p>没有接口，使用 CGLIB 动态代理</p>
<p>创建子类的代理对象，增强类的方法</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/CGLIB%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86.png" alt="CGLIB动态代理"></p>
</li>
</ul>
<h3 id="JDK-动态代理"><a href="#JDK-动态代理" class="headerlink" title="JDK 动态代理"></a>JDK 动态代理</h3><p>使用 JDK 动态代理，使用 <code>java.lang.reflect.Proxy</code> 类里面的方法创建代理对象</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/newProxyInstance%E6%96%B9%E6%B3%95.png" alt="newProxyInstance方法"></p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/newProxyInstance%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0.png" alt="newProxyInstance方法参数"></p>
<p>代码演示：</p>
<ol>
<li><p>创建接口，定义方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserDao</span> &#123;</span><br><span class="line">    <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span>;</span><br><span class="line"></span><br><span class="line">    String <span class="title function_">update</span><span class="params">(String id)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


</li>
<li><p>创建接口实现类，实现方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDaoImpl</span> <span class="keyword">implements</span> <span class="title class_">UserDao</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;add 方法执行&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> a + b;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">update</span><span class="params">(String id)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;update 方法执行&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> id;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用 <code>java.lang.reflect.Proxy</code> 类创建接口代理对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JdkProxy</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 创建接口实现类代理对象</span></span><br><span class="line">        Class[] interfaces = &#123;UserDao.class&#125;;</span><br><span class="line">        <span class="type">UserDao</span> <span class="variable">userDao</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UserDaoImpl</span>(); <span class="comment">// 被代理对象</span></span><br><span class="line">        <span class="type">UserDao</span> <span class="variable">proxyInstance</span> <span class="operator">=</span></span><br><span class="line">                (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(),</span><br><span class="line">                        interfaces, <span class="keyword">new</span> <span class="title class_">UserDaoProxy</span>(userDao));</span><br><span class="line">        System.out.println(proxyInstance.add(<span class="number">2</span>, <span class="number">3</span>));</span><br><span class="line">        System.out.println(proxyInstance.update(<span class="string">&quot;abc&quot;</span>));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建代理对象代码</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">UserDaoProxy</span> <span class="keyword">implements</span> <span class="title class_">InvocationHandler</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Object obj;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 把被代理对象传递过来</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">UserDaoProxy</span><span class="params">(Object obj)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.obj = obj;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 增强的逻辑</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">invoke</span><span class="params">(Object proxy, Method method, Object[] args)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">        <span class="comment">// 方法之前</span></span><br><span class="line">        System.out.println(method.getName() + <span class="string">&quot; 方法之前执行，参数：&quot;</span> + Arrays.toString(args));</span><br><span class="line">        <span class="comment">// 被增强的方法执行</span></span><br><span class="line">        <span class="type">Object</span> <span class="variable">returnValue</span> <span class="operator">=</span> method.invoke(obj, args);</span><br><span class="line">        <span class="comment">// 方法之后</span></span><br><span class="line">        System.out.println(method.getName() + <span class="string">&quot; 方法之后执行&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> returnValue;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<p>输出：</p>
<figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">add</span> 方法之前执行，参数：[<span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="built_in">add</span> 方法执行</span><br><span class="line"><span class="built_in">add</span> 方法之后执行</span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="keyword">update</span> 方法之前执行，参数：[<span class="keyword">abc</span>]</span><br><span class="line"><span class="keyword">update</span> 方法执行</span><br><span class="line"><span class="keyword">update</span> 方法之后执行</span><br><span class="line"><span class="keyword">abc</span></span><br></pre></td></tr></table></figure>



<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/InvocationHandler%E6%8E%A5%E5%8F%A3.png" alt="InvocationHandler接口"></p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/InvocationHandler.invoke%E6%96%B9%E6%B3%95.png" alt="InvocationHandler.invoke方法.png"></p>
<h2 id="AOP-术语"><a href="#AOP-术语" class="headerlink" title="AOP 术语"></a>AOP 术语</h2><ol>
<li>连接点：类中可以被增强的方法称为连接点</li>
<li>切入点：实际被真正增强的方法称为切入点</li>
<li>通知（增强）：实际增强的逻辑部分称为通知（增强）<ul>
<li>前置通知</li>
<li>后置通知</li>
<li>环绕通知</li>
<li>异常通知</li>
<li>最终通知</li>
</ul>
</li>
<li>切面：把通知应用到切入点的过程</li>
</ol>
<h2 id="AOP-操作"><a href="#AOP-操作" class="headerlink" title="AOP 操作"></a>AOP 操作</h2><p>Spring 框架一般基于 AspectJ 实现 AOP 操作</p>
<p>AspectJ 不是 Spring 组成部分，而是独立的 AOP 框架，但是一般把 AspectJ 和 Spring 框架一起使用，进行 AOP 操作</p>
<p>Spring 基于 AspectJ 实现 AOP 操作有两种方式：xml 配置文件方式、注解方式。</p>
<h3 id="引入依赖"><a href="#引入依赖" class="headerlink" title="引入依赖"></a>引入依赖</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-context<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-aspects<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/AOP%E4%BE%9D%E8%B5%96%E5%9B%BE.png" alt="AOP依赖图"></p>
<h3 id="切入点表达式"><a href="#切入点表达式" class="headerlink" title="切入点表达式"></a>切入点表达式</h3><p>切入点表达式作用：指明对哪个类的哪个方法进行增强</p>
<p>语法结构：</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">execution(<span class="selector-attr">[权限修饰符]</span><span class="selector-attr">[返回类型]</span><span class="selector-attr">[全类名]</span><span class="selector-attr">[方法名]</span>(<span class="selector-attr">[参数列表]</span>))</span><br></pre></td></tr></table></figure>

<p>例 1：对 <code>com.yin.spring5.UserDao#add</code> 方法进行增强</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">execution</span><span class="params">(* com.yin.spring5.UserDao.add(..)</span></span>)    <span class="comment">// 权限修饰符省略</span></span><br></pre></td></tr></table></figure>

<p>例 2：对 <code>com.yin.spring5.UserDao</code> 类中所有方法增强</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">execution</span><span class="params">(* com.yin.spring5.UserDao.*(..)</span></span>)    <span class="comment">// 权限修饰符省略</span></span><br></pre></td></tr></table></figure>

<p>例 2：对 <code>com.yin.spring5</code> 包下所有类中所有方法增强</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">execution</span><span class="params">(* com.yin.spring5.*.*(..)</span></span>)    <span class="comment">// 权限修饰符省略</span></span><br></pre></td></tr></table></figure>



<h3 id="基于注解"><a href="#基于注解" class="headerlink" title="基于注解"></a>基于注解</h3><ol>
<li><p>创建类，在类中定义方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">add</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;User.add 方法执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>创建增强类，编写增强逻辑</p>
<p>在增强类中，创建方法，让不同的方法代表不同的通知</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserProxy</span> &#123;</span><br><span class="line">    <span class="comment">// 前置通知</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">before</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserProxy.before 方法执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    ......</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>进行通知的配置</p>
<ol>
<li><p>配置文件开启注解扫描</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.yin.spring5.anno&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>使用注解创建 User 和 UserProxy 对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">User</span> &#123;...&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserProxy</span> &#123;...&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>在增强类上面添加注解 <code>@Aspect</code> </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserProxy</span> &#123;...&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>配置文件开启生成代理对象</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--开启 Aspect 生成代理对象，要引入aop名称空间--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">aop:aspectj-autoproxy</span>/&gt;</span></span><br></pre></td></tr></table></figure></li>
</ol>
</li>
<li><p>配置不同类型的通知</p>
<p>在增强类的里面，在作为通知方法上面添加通知类型注解，使用切入点表达式配置</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserProxy</span> &#123;</span><br><span class="line">    <span class="comment">// 前置通知</span></span><br><span class="line">    <span class="meta">@Before(&quot;execution(* com.yin.spring5.anno.User.add(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">before</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserProxy.before 方法执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 最终通知</span></span><br><span class="line">    <span class="meta">@After(&quot;execution(* com.yin.spring5.anno.User.add(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">after</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserProxy.after 方法执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 后置通知（返回通知）</span></span><br><span class="line">    <span class="meta">@AfterReturning(&quot;execution(* com.yin.spring5.anno.User.add(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterReturning</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserProxy.afterReturning 方法执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 异常通知</span></span><br><span class="line">    <span class="meta">@AfterThrowing(&quot;execution(* com.yin.spring5.anno.User.add(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterThrowing</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserProxy.afterThrowing 方法执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 环绕通知</span></span><br><span class="line">    <span class="meta">@Around(&quot;execution(* com.yin.spring5.anno.User.add(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">around</span><span class="params">(ProceedingJoinPoint proceedingJoinPoint)</span> <span class="keyword">throws</span> Throwable &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;环绕之前。。。&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 被增强的方法执行</span></span><br><span class="line">        proceedingJoinPoint.proceed();</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;环绕之后。。。&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<p>测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring1.xml&quot;</span>);</span><br><span class="line">    <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;user&quot;</span>, User.class);</span><br><span class="line">    user.add();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">环绕之前。。。</span><br><span class="line">UserProxy.<span class="keyword">before</span> 方法执行</span><br><span class="line"><span class="keyword">User</span>.<span class="keyword">add</span> 方法执行</span><br><span class="line">UserProxy.afterReturning 方法执行</span><br><span class="line">UserProxy.<span class="keyword">after</span> 方法执行</span><br><span class="line">环绕之后。。。</span><br></pre></td></tr></table></figure>

<p><strong>抽取相同的切入点</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserProxy</span> &#123;</span><br><span class="line">    <span class="comment">// 抽取相同的切入点</span></span><br><span class="line">    <span class="meta">@Pointcut(&quot;execution(* com.yin.spring5.anno.User.add(..))&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">pointDemo</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 前置通知</span></span><br><span class="line">    <span class="meta">@Before(&quot;pointDemo()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">before</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;UserProxy.before 方法执行&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>有多个增强类对同一个方法进行增强，设置增强类优先级</p>
<p>在增强类上添加注解 <code>@Order(value = )</code> ，数字越小，优先级越高</p>
<p><strong>完全使用注解</strong></p>
<p>创建配置类，不需要创建 xml 配置文件</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@ComponentScan(basePackages = &quot;com.yin.spring5.anno&quot;)</span></span><br><span class="line"><span class="meta">@EnableAspectJAutoProxy(proxyTargetClass = true)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AopConfig</span> &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="基于-xml-配置文件"><a href="#基于-xml-配置文件" class="headerlink" title="基于 xml 配置文件"></a>基于 xml 配置文件</h3><hr>
<h1 id="JdbcTemplate"><a href="#JdbcTemplate" class="headerlink" title="JdbcTemplate"></a>JdbcTemplate</h1><p>什么是 JdbcTemplate ？</p>
<p>Spring 对 JDBC 进行封装，使用 JdbcTemplate 方便实现对数据库操作</p>
<h2 id="环境配置"><a href="#环境配置" class="headerlink" title="环境配置"></a>环境配置</h2><h3 id="引入依赖-1"><a href="#引入依赖-1" class="headerlink" title="引入依赖"></a>引入依赖</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-context<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>8.0.19<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/com.alibaba/druid --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.1.22<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/JdbcTemplate%E4%BE%9D%E8%B5%96%E5%9B%BE.png" alt="JdbcTemplate依赖图"></p>
<h3 id="配置数据库连接池"><a href="#配置数据库连接池" class="headerlink" title="配置数据库连接池"></a>配置数据库连接池</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--引入外部数据库配置文件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">context:property-placeholder</span> <span class="attr">location</span>=<span class="string">&quot;classpath:db-config.properties&quot;</span>/&gt;</span></span><br><span class="line"><span class="comment">&lt;!--Druid 数据源--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.alibaba.druid.pool.DruidDataSource&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">destroy-method</span>=<span class="string">&quot;close&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClassName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.driverClass&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.url&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.username&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="配置-JdbcTemplate"><a href="#配置-JdbcTemplate" class="headerlink" title="配置 JdbcTemplate"></a>配置 JdbcTemplate</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--JdbcTemplate--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;jdbcTemplate&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.core.JdbcTemplate&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--注入数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="编写类文件"><a href="#编写类文件" class="headerlink" title="编写类文件"></a>编写类文件</h3><p>编写 Book 实体类，创建对应数据表</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Book</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String title;</span><br><span class="line">    <span class="keyword">private</span> String author;</span><br><span class="line">    <span class="keyword">private</span> BigDecimal price;</span><br><span class="line">    <span class="comment">// 此处省略 getter setter toString 等方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>环境一览</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=<span class="string">&quot;1.0&quot;</span> encoding=<span class="string">&quot;UTF-8&quot;</span>?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--注意：此处文件头等信息略去--&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--组件扫描--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">&quot;com.yin.spring5&quot;</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--引入外部数据库配置文件--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:property-placeholder</span> <span class="attr">location</span>=<span class="string">&quot;classpath:db-config.properties&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--Druid 数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">class</span>=<span class="string">&quot;com.alibaba.druid.pool.DruidDataSource&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">destroy-method</span>=<span class="string">&quot;close&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driverClassName&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.driverClass&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.url&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.username&#125;&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--JdbcTemplate--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;jdbcTemplate&quot;</span> <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.core.JdbcTemplate&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--注入数据源--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">BookDao</span> &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Repository</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookDaoImpl</span> <span class="keyword">implements</span> <span class="title class_">BookDao</span> &#123;</span><br><span class="line">    JdbcTemplate jdbcTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setJdbcTemplate</span><span class="params">(JdbcTemplate jdbcTemplate)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.jdbcTemplate = jdbcTemplate;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BookService</span> &#123;</span><br><span class="line">    BookDao bookDao;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setBookDao</span><span class="params">(BookDao bookDao)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.bookDao = bookDao;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="操作数据库"><a href="#操作数据库" class="headerlink" title="操作数据库"></a>操作数据库</h2><h3 id="增"><a href="#增" class="headerlink" title="增"></a>增</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">insert</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;INSERT INTO book(title,author,price) VALUES(?,?,?)&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.update(sql, book.getTitle(), book.getAuthor(), book.getPrice());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="改"><a href="#改" class="headerlink" title="改"></a>改</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">update</span><span class="params">(Book book)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;UPDATE book SET title=?, author=?, price=? WHERE id=?&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.update(sql, book.getTitle(), book.getAuthor(),</span><br><span class="line">                               book.getPrice(), book.getId());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="删"><a href="#删" class="headerlink" title="删"></a>删</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">delete</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;DELETE FROM book WHERE id=?&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.update(sql, id);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="查"><a href="#查" class="headerlink" title="查"></a>查</h3><h4 id="某个值"><a href="#某个值" class="headerlink" title="某个值"></a>某个值</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span> <span class="title function_">recordCount</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;SELECT COUNT(*) FROM book&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.queryForObject(sql, Integer.TYPE);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> Book <span class="title function_">getOneById</span><span class="params">(Integer id)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;SELECT id, title, author, price FROM book WHERE id=?&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.queryForObject(sql, <span class="keyword">new</span> <span class="title class_">BeanPropertyRowMapper</span>&lt;&gt;(Book.class), id);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> List&lt;Book&gt; <span class="title function_">getAll</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;SELECT * FROM book&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.query(sql, <span class="keyword">new</span> <span class="title class_">BeanPropertyRowMapper</span>&lt;&gt;(Book.class));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="批量操作"><a href="#批量操作" class="headerlink" title="批量操作"></a>批量操作</h3><h4 id="批量添加"><a href="#批量添加" class="headerlink" title="批量添加"></a>批量添加</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span>[] batchInsert(List&lt;Object[]&gt; bookList) &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;INSERT INTO book(title,author,price) VALUES(?,?,?)&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.batchUpdate(sql, bookList);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testBatchAdd</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring1.xml&quot;</span>);</span><br><span class="line">    <span class="type">BookService</span> <span class="variable">bookService</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;bookService&quot;</span>, BookService.class);</span><br><span class="line">    List&lt;Object[]&gt; bookList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    <span class="comment">// 按占位符顺序写参数</span></span><br><span class="line">    Object[] book1 = &#123;<span class="string">&quot;城南旧事&quot;</span>, <span class="string">&quot;林海音&quot;</span>, <span class="number">29.00</span>&#125;;</span><br><span class="line">    Object[] book2 = &#123;<span class="string">&quot;追风筝的人&quot;</span>, <span class="string">&quot;忘了&quot;</span>, <span class="number">29.00</span>&#125;;</span><br><span class="line">    Object[] book3 = &#123;<span class="string">&quot;小王子&quot;</span>, <span class="string">&quot;安东尼&quot;</span>, <span class="number">19.00</span>&#125;;</span><br><span class="line">    bookList.add(book1);</span><br><span class="line">    bookList.add(book2);</span><br><span class="line">    bookList.add(book3);</span><br><span class="line">    bookService.batchAddBook(bookList);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="批量修改"><a href="#批量修改" class="headerlink" title="批量修改"></a>批量修改</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span>[] batchUpdate(List&lt;Object[]&gt; bookList) &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;UPDATE book SET title=?, author=?, price=? WHERE id=?&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.batchUpdate(sql, bookList);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testBatchUpdate</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring1.xml&quot;</span>);</span><br><span class="line">    <span class="type">BookService</span> <span class="variable">bookService</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;bookService&quot;</span>, BookService.class);</span><br><span class="line">    List&lt;Object[]&gt; bookList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    <span class="comment">// 按占位符顺序写参数</span></span><br><span class="line">    Object[] book1 = &#123;<span class="string">&quot;城南旧事&quot;</span>, <span class="string">&quot;林海音（台湾）&quot;</span>, <span class="number">26.00</span>, <span class="number">24</span>&#125;;</span><br><span class="line">    Object[] book2 = &#123;<span class="string">&quot;追风筝的人&quot;</span>, <span class="string">&quot;还是没想起来&quot;</span>, <span class="number">29.00</span>, <span class="number">25</span>&#125;;</span><br><span class="line">    Object[] book3 = &#123;<span class="string">&quot;小王子&quot;</span>, <span class="string">&quot;安东尼奥&quot;</span>, <span class="number">20.00</span>, <span class="number">26</span>&#125;;</span><br><span class="line">    bookList.add(book1);</span><br><span class="line">    bookList.add(book2);</span><br><span class="line">    bookList.add(book3);</span><br><span class="line">    bookService.batchUpdateBook(bookList);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="批量删除"><a href="#批量删除" class="headerlink" title="批量删除"></a>批量删除</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="keyword">public</span> <span class="type">int</span>[] batchDelete(List&lt;Object[]&gt; idList) &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;DELETE FROM book WHERE id=?&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> jdbcTemplate.batchUpdate(sql, idList);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">testBatchDelete</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">ApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassPathXmlApplicationContext</span>(<span class="string">&quot;spring1.xml&quot;</span>);</span><br><span class="line">    <span class="type">BookService</span> <span class="variable">bookService</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;bookService&quot;</span>, BookService.class);</span><br><span class="line">    List&lt;Object[]&gt; idList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">    <span class="comment">// 按占位符顺序写参数</span></span><br><span class="line">    Object[] id1 = &#123;<span class="number">19</span>&#125;;</span><br><span class="line">    Object[] id2 = &#123;<span class="number">20</span>&#125;;</span><br><span class="line">    Object[] id3 = &#123;<span class="number">21</span>&#125;;</span><br><span class="line">    Object[] id4 = &#123;<span class="number">25</span>&#125;;</span><br><span class="line">    idList.add(id1);</span><br><span class="line">    idList.add(id2);</span><br><span class="line">    idList.add(id3);</span><br><span class="line">    idList.add(id4);</span><br><span class="line">    bookService.batchDeleteBook(idList);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<hr>
<h1 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h1><h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><ol>
<li><p>什么是事务？</p>
<p>事务是数据库操作的最基本单元，逻辑上的一组操作，要么都成功，如果有一个操作失败，所有操作都失败</p>
<p>典型场景：银行转账</p>
</li>
<li><p>事务四个特性 ACID</p>
<ul>
<li><p><strong>原子性 Atomicity</strong></p>
<p>原子性是指事务是一个不可分割的工作单位，事务中的操作要么都成功，要么都不成功</p>
</li>
<li><p><strong>一致性 Consistency</strong></p>
<p>事务必须使数据库从一个一致性状态变换到另一个一致性状态</p>
</li>
<li><p><strong>隔离性 Isolation</strong></p>
<p>事务的隔离性是指一个事务的执行不能被其他事务干扰，即一个事务内部的操作及使用的数据对并发的其他事务是隔离的，并发执行的各个事务之间不能互相干扰</p>
</li>
<li><p><strong>持久性 Durability</strong></p>
<p>持久性是指一个事务一旦被提交，它对数据库中数据的改变就是永久性的，接下来的其他操作和数据库故障不应该对其有任何影响</p>
</li>
</ul>
</li>
</ol>
<h2 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h2><p>引入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-context<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-jdbc<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/org.springframework/spring-orm --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-orm<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>$&#123;spring.version&#125;<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>8.0.19<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- https://mvnrepository.com/artifact/com.alibaba/druid --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>druid<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.1.22<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/%E4%BA%8B%E5%8A%A1%E4%BE%9D%E8%B5%96%E5%9B%BE.png" alt="事务依赖图"></p>
<p>创建数据库表</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">use `jdbc_template`;</span><br><span class="line"></span><br><span class="line">create table `account` (</span><br><span class="line">    `id`      int primary key auto_increment comment &#x27;id&#x27;,</span><br><span class="line">    `name`    varchar(50) comment &#x27;姓名&#x27;,</span><br><span class="line">    `balance` int comment &#x27;余额&#x27;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">insert into `account`(`name`, `balance`)</span><br><span class="line">VALUES (&#x27;亚索&#x27;, 1000),</span><br><span class="line">       (&#x27;永恩&#x27;, 1000);</span><br></pre></td></tr></table></figure>

<p>编写实体类、DAO、Service 等</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Account</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> Integer balance;</span><br><span class="line">    <span class="comment">// 此处省略 getter setter toString 等方法</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">AccountDao</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 增加金额</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id    用户id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> money 金额数目</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">addMoney</span><span class="params">(<span class="type">int</span> id, <span class="type">int</span> money)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 扣除金额</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id    用户id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> money 金额数目</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">deductMoney</span><span class="params">(<span class="type">int</span> id, <span class="type">int</span> money)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Repository</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountDaoImpl</span> <span class="keyword">implements</span> <span class="title class_">AccountDao</span> &#123;</span><br><span class="line">    <span class="keyword">final</span> JdbcTemplate jdbcTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">AccountDaoImpl</span><span class="params">(JdbcTemplate jdbcTemplate)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.jdbcTemplate = jdbcTemplate;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addMoney</span><span class="params">(<span class="type">int</span> id, <span class="type">int</span> money)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;UPDATE account SET balance=balance+? WHERE id=?&quot;</span>;</span><br><span class="line">        jdbcTemplate.update(sql, money, id);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">deductMoney</span><span class="params">(<span class="type">int</span> id, <span class="type">int</span> money)</span> &#123;</span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;UPDATE account SET balance=balance-? WHERE id=?&quot;</span>;</span><br><span class="line">        jdbcTemplate.update(sql, money, id);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountService</span> &#123;</span><br><span class="line">    <span class="keyword">final</span> AccountDao accountDao;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">AccountService</span><span class="params">(AccountDao accountDao)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.accountDao = accountDao;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 转账业务</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> deductId 扣除金额方id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> addId    增加金额方id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> money    转账金额数目</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">transferAccount</span><span class="params">(<span class="type">int</span> deductId, <span class="type">int</span> addId, <span class="type">int</span> money)</span> &#123;</span><br><span class="line">        accountDao.deductMoney(deductId, money);</span><br><span class="line">        accountDao.addMoney(addId, money);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上面的代码，如果正常执行是没有问题的，但是如果代码执行过程中出现异常，会有问题</p>
<p>比如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">transferAccount</span><span class="params">(<span class="type">int</span> deductId, <span class="type">int</span> addId, <span class="type">int</span> money)</span> &#123;</span><br><span class="line">    accountDao.deductMoney(deductId, money);</span><br><span class="line">    <span class="comment">// 模拟异常</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">10</span> / <span class="number">0</span>;</span><br><span class="line">    accountDao.addMoney(addId, money);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>为避免诸如上述问题，就需要事务。</p>
<p>事务操作流程：</p>
<ol>
<li>开启事务</li>
<li>业务操作</li>
<li>若无异常，提交事务</li>
<li>出现异常，回滚事务</li>
</ol>
<h2 id="Spring-事务管理"><a href="#Spring-事务管理" class="headerlink" title="Spring 事务管理"></a>Spring 事务管理</h2><ol>
<li><p>事务一般添加到 Service 层</p>
</li>
<li><p>Spring 进行事务管理有两种方式：编程式事务管理 和 <strong>声明式事务管理</strong>。一般都使用声明式事务管理。</p>
</li>
<li><p>声明式事务管理有两种方式：<strong>基于注解</strong>，基于 xml 配置文件。</p>
</li>
<li><p>Spring 进行声明式事务管理，<strong>底层使用 AOP 原理</strong>。</p>
</li>
<li><p>Spring 事务管理 API</p>
<p>提供 <code>PlatformTransactionManager</code> 接口，代表事务管理器，这个接口针对不同框架提供不同的实现类</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/PlatformTransactionManager%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BF%E6%A0%91.png" alt="PlatformTransactionManager接口继承树"></p>
</li>
</ol>
<h2 id="基于注解的声明式事务管理"><a href="#基于注解的声明式事务管理" class="headerlink" title="基于注解的声明式事务管理"></a>基于注解的声明式事务管理</h2><p>配置事务管理器</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--配置事务管理器--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;transactionManager&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--注入数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>开启事务注解</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--开启事务注解--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tx:annotation-driven</span> <span class="attr">transaction-manager</span>=<span class="string">&quot;transactionManager&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>上面讲到，事务一般添加到 Service 层</p>
<p>在 Service 类上（或者类中的方法上）添加事务注解 <code>@Transactional</code> </p>
<p>事务注解 <code>@Transactional</code> 既可以添加到类上，也可以添加到方法上</p>
<ul>
<li>如果添加到类上，则该类中的所有方法都会添加事务</li>
<li>如果添加到方法上，则只会给该方法添加事务</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountService</span> &#123;...&#125;</span><br></pre></td></tr></table></figure>

<p>事务注解 <code>@Transactional</code> 部分参数：</p>
<ul>
<li><p><code>propagation</code> ：事务传播类型（默认 <code>REQUIRED</code>）</p>
<p>多事务方法直接进行调用，这个过程中事务是如何进行管理的</p>
</li>
<li><p><code>isolation</code> ：事务隔离级别</p>
<p>事务特性之一。不考虑隔离性会产生很多问题，三个读问题：<strong>脏读、不可重复读、幻读（虚读）</strong>。</p>
<ul>
<li>脏读：一个未提交事务读取到另一个未提交事务的数据</li>
<li>不可重复读：一个未提交事务读取到另一个提交事务修改数据</li>
<li>幻读：一个未提交事务读取到另一个提交事务添加数据</li>
</ul>
</li>
<li><p><code>timeout</code> ：事务超时时间（秒，默认 -1 即永不超时）</p>
<p>事务需要在指定时间内进行提交，如果不提交就会回滚</p>
</li>
<li><p><code>readOnly</code> ：事务是否只读（默认 <code>false</code>）</p>
</li>
<li><p><code>rollbackFor</code> ：指明哪些异常类型进行事务回滚</p>
</li>
<li><p><code>noRollbackFor</code> ：指明哪些异常类型不进行事务回滚</p>
</li>
</ul>
<p>事务方法：对数据库表数据进行变化的操作</p>
<p>事务的传播行为可以由传播类型指定，Spring 定义了 7 种传播类型</p>
<table>
<thead>
<tr>
<th align="left">传播类型</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td align="left">REQUIRED</td>
<td>如果有事务在运行，当前的方法就在这个事务内运行；否则，就启动一个新的事务，并在自己的事务内运行</td>
</tr>
<tr>
<td align="left">REQUIRES_NEW</td>
<td>当前的方法必须启动新事务，并在它自己的事务内运行；如果有事务正在运行，应该将它挂起</td>
</tr>
<tr>
<td align="left">SUPPORTS</td>
<td>如果有事务在运行，当前的方法就在这个事务内运行，否则它可以不运行在事务中</td>
</tr>
<tr>
<td align="left">NOT_SUPPORTED</td>
<td>当前的方法不应该运行在事务中，如果有运行的事务，将它挂起</td>
</tr>
<tr>
<td align="left">MANDATORY</td>
<td>当前的方法必须运行在事务内部，如果没有正在运行的事务，就抛出异常</td>
</tr>
<tr>
<td align="left">NEVER</td>
<td>当前的方法不应该运行在事务中，如果有运行的事务，就抛出异常</td>
</tr>
<tr>
<td align="left">NESTED</td>
<td>如果有事务在运行，当前的方法就应该在这个事务的嵌套事务内运行；否则，就启动一个新的事务，并在它自己的事务内运行</td>
</tr>
</tbody></table>
<p>事务隔离级别</p>
<table>
<thead>
<tr>
<th>隔离级别</th>
<th>脏读</th>
<th>不可重复读</th>
<th>幻读</th>
</tr>
</thead>
<tbody><tr>
<td>READ_UNCOMMITTED（读未提交）</td>
<td>有</td>
<td>有</td>
<td>有</td>
</tr>
<tr>
<td>READ_COMMITTED（读已提交）</td>
<td>无</td>
<td>有</td>
<td>有</td>
</tr>
<tr>
<td>REPEATABLE_READ（可重复读，MySQL默认）</td>
<td>无</td>
<td>无</td>
<td>有</td>
</tr>
<tr>
<td>SERIALIZABLE（串行化）</td>
<td>无</td>
<td>无</td>
<td>无</td>
</tr>
</tbody></table>
<h2 id="基于-XML-的声明式事务管理"><a href="#基于-XML-的声明式事务管理" class="headerlink" title="基于 XML 的声明式事务管理"></a>基于 XML 的声明式事务管理</h2><p>第一步，配置事务管理器；第二步，配置通知；第三步，配置切入点和切面</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--基于 XML 的事务--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--1.配置事务管理器--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">&quot;transactionManager2&quot;</span></span></span><br><span class="line"><span class="tag">      <span class="attr">class</span>=<span class="string">&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--注入数据源--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;dataSource&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;dataSource2&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--2.配置通知--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">tx:advice</span> <span class="attr">id</span>=<span class="string">&quot;txAdvice&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--配置事务参数--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tx:attributes</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--指定哪种规则的方法上添加事务--&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">tx:method</span> <span class="attr">name</span>=<span class="string">&quot;transferAccount&quot;</span> <span class="attr">propagation</span>=<span class="string">&quot;REQUIRED&quot;</span></span></span><br><span class="line"><span class="tag">                   <span class="attr">isolation</span>=<span class="string">&quot;REPEATABLE_READ&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tx:attributes</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">tx:advice</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--3.配置切入点和切面--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">aop:config</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--配置切入点--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:pointcut</span> <span class="attr">id</span>=<span class="string">&quot;myPointCut&quot;</span></span></span><br><span class="line"><span class="tag">                  <span class="attr">expression</span>=<span class="string">&quot;execution(* com.yin.spring5.service.AccountService.*(..))&quot;</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--配置切面--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">aop:advisor</span> <span class="attr">advice-ref</span>=<span class="string">&quot;txAdvice&quot;</span> <span class="attr">pointcut-ref</span>=<span class="string">&quot;myPointCut&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">aop:config</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h2 id="完全注解"><a href="#完全注解" class="headerlink" title="完全注解"></a>完全注解</h2><p>创建配置类，代替 xml 配置文件</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span>    <span class="comment">// 配置类</span></span><br><span class="line"><span class="meta">@ComponentScan(basePackages = &quot;com.yin.spring5&quot;)</span>    <span class="comment">// 组件扫描</span></span><br><span class="line"><span class="meta">@EnableTransactionManagement</span>    <span class="comment">// 开启事务</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TxConfig</span> &#123;</span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> DataSource <span class="title function_">dataSource</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">DruidDataSource</span> <span class="variable">dataSource</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DruidDataSource</span>();</span><br><span class="line">        dataSource.setDriverClassName(<span class="string">&quot;com.mysql.cj.jdbc.Driver&quot;</span>);</span><br><span class="line">        dataSource.setUrl(<span class="string">&quot;jdbc:mysql://localhost:3306/jdbc_template&quot;</span> +</span><br><span class="line">                <span class="string">&quot;?serverTimezone=Asia/Shanghai&quot;</span>);</span><br><span class="line">        dataSource.setUsername(<span class="string">&quot;root&quot;</span>);</span><br><span class="line">        dataSource.setPassword(<span class="string">&quot;123456&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> dataSource;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> JdbcTemplate <span class="title function_">jdbcTemplate</span><span class="params">(DataSource dataSource)</span> &#123;</span><br><span class="line">        <span class="type">JdbcTemplate</span> <span class="variable">jdbcTemplate</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">JdbcTemplate</span>();</span><br><span class="line">        jdbcTemplate.setDataSource(dataSource);</span><br><span class="line">        <span class="keyword">return</span> jdbcTemplate;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="keyword">public</span> DataSourceTransactionManager <span class="title function_">transactionManager</span><span class="params">(DataSource dataSource)</span> &#123;</span><br><span class="line">        <span class="type">DataSourceTransactionManager</span> <span class="variable">transactionManager</span> <span class="operator">=</span></span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">DataSourceTransactionManager</span>();</span><br><span class="line">        transactionManager.setDataSource(dataSource);</span><br><span class="line">        <span class="keyword">return</span> transactionManager;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<hr>
<h1 id="Spring-5-新功能"><a href="#Spring-5-新功能" class="headerlink" title="Spring 5 新功能"></a>Spring 5 新功能</h1><ol>
<li><p>Spring 5 基于 Java 8，运行时兼容 Java 9，移除了不建议使用的类和方法。</p>
</li>
<li><p>Spring 5 自带了通用的日志封装</p>
<p>Spring 5 移除了 <code>Log4jConfigListener</code>，官方建议使用 Log4j2</p>
</li>
<li><p>Spring 5 核心注解支持 <code>@Nullable</code> 注解</p>
<p><code>@Nullable</code> 注解可以用在方法上、属性上、参数上，表示方法返回值、属性、参数可以为空</p>
</li>
<li><p>支持函数式风格 GenericApplicationContext &#x2F; AnnotationConfigApplicationContext</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test4</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">GenericApplicationContext</span> <span class="variable">context</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">GenericApplicationContext</span>();</span><br><span class="line">    context.refresh();</span><br><span class="line">    <span class="comment">// 注册 bean</span></span><br><span class="line">    context.registerBean(<span class="string">&quot;acct&quot;</span>, Account.class, Account::<span class="keyword">new</span>);</span><br><span class="line">    <span class="comment">// 获取注册的对象</span></span><br><span class="line">    <span class="type">Account</span> <span class="variable">acct</span> <span class="operator">=</span> context.getBean(<span class="string">&quot;acct&quot;</span>, Account.class);</span><br><span class="line">    System.out.println(acct);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


</li>
<li><p>Spring 5 支持整合 JUnit 5</p>
</li>
</ol>
<p>Spring 5 整合 Log4j2</p>
<ol>
<li>引入依赖</li>
<li>创建 log4j2.xml 配置文件（文件名固定）</li>
</ol>
<hr>
<h1 id="Spring-WebFlux"><a href="#Spring-WebFlux" class="headerlink" title="Spring WebFlux"></a>Spring WebFlux</h1><h2 id="Spring-WebFlux-介绍"><a href="#Spring-WebFlux-介绍" class="headerlink" title="Spring WebFlux 介绍"></a>Spring WebFlux 介绍</h2><p>Spring WebFlux 是 Spring 5 新增的模块，用于 Web 开发，功能与 Spring MVC 类似，使用当前比较流行的响应式编程</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/Spring%205%20%E6%A8%A1%E5%9D%97%E5%9B%BE.png" alt="Spring 5 模块图"></p>
<p>使用传统 Web 框架，比如 Spring MVC，这些基于 Servlet 容器。WebFlux 是一种异步非阻塞式的框架，异步非阻塞的框架在 Servlet 3.1 以后才支持，核心是基于 Reactor 的相关 API 实现的。</p>
<h3 id="什么是异步非阻塞？"><a href="#什么是异步非阻塞？" class="headerlink" title="什么是异步非阻塞？"></a>什么是异步非阻塞？</h3><ul>
<li><p>同步与异步</p>
<p>异步和同步针对调用者。调用者发送请求，如果等着对方回应之后才去左其他事就是同步；如果发送请求后不等着对方回应就去做其他事就是异步。</p>
</li>
<li><p>阻塞与非阻塞</p>
<p>阻塞和非阻塞针对被调用者。被调用者收到请求之后，做完请求任务之后才给出反馈就是阻塞，收到请求之后马上给出反馈然后再去做事情就是非阻塞。</p>
</li>
</ul>
<h3 id="WebFlux-特点"><a href="#WebFlux-特点" class="headerlink" title="WebFlux 特点"></a>WebFlux 特点</h3><ol>
<li>非阻塞式：在有限资源下，提高系统吞吐量和伸缩性，以 Reactor 为基础实现响应式编程</li>
<li>函数式编程：使用 Java 8 函数式编程方式实现路由请求</li>
</ol>
<h3 id="对比-Spring-MVC"><a href="#对比-Spring-MVC" class="headerlink" title="对比 Spring MVC"></a>对比 Spring MVC</h3><ol>
<li>两种方式都可以使用注解方式，都运行在 Tomcat 等容器中</li>
<li>SpringMVC 采用命令式编程，WebFlux 采用异步响应式编程</li>
</ol>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/SpringMVC%E5%AF%B9%E6%AF%94WebFlux.png" alt="SpringMVC对比WebFlux"></p>
<h2 id="响应式编程"><a href="#响应式编程" class="headerlink" title="响应式编程"></a>响应式编程</h2><h3 id="什么是响应式编程？"><a href="#什么是响应式编程？" class="headerlink" title="什么是响应式编程？"></a><strong>什么是响应式编程？</strong></h3><p>响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流，而相关的计算模型会自动将变化的值通过数据流进行传播。</p>
<p>例如，在命令式编程环境中，<code>a=b+c</code> 表示将表达式的结果赋给 a，而之后改变 b 或 c 的值不会影响 a。但在响应式编程中，a 的值会随着 b 或 c 的更新而更新。<br>电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似 “&#x3D;B1+C1” 的公式，而包含公式的单元格的值会依据其他单元格的值的变化而变化。</p>
<h3 id="Java-8-及之前版本"><a href="#Java-8-及之前版本" class="headerlink" title="Java 8 及之前版本"></a><strong>Java 8 及之前版本</strong></h3><p>提供的观察者模式两个类：Observer 接口，Observable 类（两者从 Java 9 开始被遗弃）</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/Java8%E5%8F%8A%E4%B9%8B%E5%89%8D%E5%93%8D%E5%BA%94%E5%BC%8F.png" alt="Java8及之前响应式"></p>
<h3 id="响应式编程（Reactor-实现）"><a href="#响应式编程（Reactor-实现）" class="headerlink" title="响应式编程（Reactor 实现）"></a><strong>响应式编程（Reactor 实现）</strong></h3><ul>
<li>响应式编程操作中，Reactor 是满足 Reactive 规范框架</li>
<li>Reactor 有两个核心类，Mono 和 Flux，这两个类实现 Publisher 接口，提供丰富操作符。Flux 对象实现发布者，返回 N 个元素；Mono 实现发布者，返回 0 或 1 个元素</li>
<li>Flux 和 Mono 都是数据流的发布者，使用 Flux 和 Mono 都可以发出<strong>三种数据信号：元素值、错误信号、完成信号</strong>。<strong>错误信号和完成信号都表示终止信号</strong>，终止信号用于告诉订阅者数据流结束了，错误信号终止数据流同时把错误信息传递给订阅者</li>
<li>三种信号特点：<ul>
<li>错误信号和完成信号都是终止信号，二者不能共存</li>
<li>如果没有发送任何元素值，而是直接发送终止信号，表示是空数据流</li>
<li>如果没有终止信号，表示是无限数据流</li>
</ul>
</li>
</ul>
<h3 id="代码演示-Flux-和-Mono"><a href="#代码演示-Flux-和-Mono" class="headerlink" title="代码演示 Flux 和 Mono"></a><strong>代码演示 Flux 和 Mono</strong></h3><p>引入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- https://mvnrepository.com/artifact/io.projectreactor/reactor-core --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.projectreactor<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>reactor-core<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>3.4.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>调用 just 方法或者其他方法只是声明数据流，数据流并没有发出，只有进行订阅之后才会触发数据流，不订阅什么都不会发生。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// just 方法直接声明</span></span><br><span class="line">Flux.just(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>).subscribe(System.out::println);</span><br><span class="line">Mono.just(<span class="number">5</span>).subscribe(System.out::println);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 其他的方法</span></span><br><span class="line">Integer[] array = &#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>&#125;;</span><br><span class="line">Flux.fromArray(array);</span><br><span class="line">List&lt;Integer&gt; list = Arrays.asList(array);</span><br><span class="line">Flux.fromIterable(list);</span><br><span class="line">Stream&lt;Integer&gt; stream = list.stream();</span><br><span class="line">Flux.fromStream(stream);</span><br></pre></td></tr></table></figure>

<h3 id="操作符"><a href="#操作符" class="headerlink" title="操作符"></a>操作符</h3><p>对数据流进行一道道操作，称为操作符，比如工厂流水线</p>
<ul>
<li><p>map：将元素映射为新元素</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/map%E6%93%8D%E4%BD%9C%E7%AC%A6%E7%A4%BA%E6%84%8F%E5%9B%BE.png" alt="map操作符示意图"></p>
</li>
<li><p>flatMap：将元素映射为流。把每个元素转换流，把转换之后多个流合并为大的流</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/flatMap%E6%93%8D%E4%BD%9C%E7%AC%A6%E7%A4%BA%E6%84%8F%E5%9B%BE.png" alt="flatMap操作符示意图"></p>
</li>
</ul>
<h2 id="WebFlux执行流程和核心-API"><a href="#WebFlux执行流程和核心-API" class="headerlink" title="WebFlux执行流程和核心 API"></a>WebFlux执行流程和核心 API</h2><p>Spring WebFlux 基于 Reactor，默认使用容器是 Netty，Netty 是高性能 NIO（Non-blocking IO，非阻塞IO） 框架。（与 NIO 相对的是 BIO，即 Blocking IO）</p>
<p>BIO 的通信方式：</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/BIO%E7%9A%84%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F.png" alt="BIO的通信方式"></p>
<p>NIO 的通信方式：</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/NIO%E7%9A%84%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F.png" alt="NIO的通信方式"></p>
<p>Spring WebFlux 执行过程与 Spring MVC 相似</p>
<p>Spring WebFlux 核心控制器 <code>DispatchHandler</code>，实现接口 <code>WebHandler</code>。</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/WebHandler%E6%8E%A5%E5%8F%A3.png" alt="WebHandler接口"></p>
<p><code>DispatcherHandler.handle</code> 方法：</p>
<p><img src="https://gitee.com/ME_WE/my-picture-repository/raw/master/Spring%205%20%E7%AC%94%E8%AE%B0%E6%8F%92%E5%9B%BE/DispatcherHandler.handle%E6%96%B9%E6%B3%95.png" alt="DispatcherHandler.handle方法"></p>
<p>在 Spring WebFlux 中，DispatcherHandler 负责请求的处理</p>
<p>以下三个都是接口：</p>
<ul>
<li><p><code>HandlerMapping</code>：请求查询到处理的方法。</p>
<blockquote>
<p>Interface to be implemented by objects that define a mapping between requests and handler objects. </p>
<p>由定义请求和处理程序对象之间的映射关系的对象实现的接口。</p>
</blockquote>
</li>
<li><p><code>HandlerAdapter</code>：真正负责请求处理。</p>
<blockquote>
<p>Contract that decouples the {@link DispatcherHandler} from the details of invoking a handler and makes it possible to support any handler type. </p>
<p>使 DispatcherHandler 与调用处理程序的详细信息分离的契约，并且可以支持任何处理程序类型。</p>
</blockquote>
</li>
<li><p><code>HandlerResultHandler</code>：响应结果处理。</p>
<blockquote>
<p>Process the {@link HandlerResult}, usually returned by an {@link HandlerAdapter}. </p>
<p>处理 HandlerResult，通常由 HandlerAdapter 返回。</p>
</blockquote>
</li>
</ul>
<p>Spring WebFlux 实现函数式编程，两个接口：</p>
<ul>
<li><code>RouterFunction</code> ：Represents a function that routes to a {@linkplain HandlerFunction handler function}. </li>
<li><code>HandlerFunction</code> ：Represents a function that handles a {@linkplain ServerRequest request}.</li>
</ul>
<h2 id="基于注解编程模型"><a href="#基于注解编程模型" class="headerlink" title="基于注解编程模型"></a>基于注解编程模型</h2><p>使用注解方式，与之前 Spring MVC 使用相似，只需要引入相关依赖，Spring Boot 自动配置相关运行容器，默认情况下使用 Netty 服务器。</p>
<p>引入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-webflux<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>编写代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 根据 id 查询 User</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> id 要查询的 id</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 查询的结果</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Mono&lt;User&gt; <span class="title function_">getUserById</span><span class="params">(<span class="type">int</span> id)</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询所有 User</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 查询的结果</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Flux&lt;User&gt; <span class="title function_">getAllUsers</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 添加 User</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> user 要添加的 User</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> 。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Mono&lt;Void&gt; <span class="title function_">saveUser</span><span class="params">(Mono&lt;User&gt; user)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">UserService</span> &#123;</span><br><span class="line">    <span class="comment">// 为了方便，这里使用 Map 代替数据库存储数据</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Map&lt;Integer, User&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">UserServiceImpl</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.map.put(<span class="number">1</span>, <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">1</span>, <span class="string">&quot;Alice&quot;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="number">18</span>));</span><br><span class="line">        <span class="built_in">this</span>.map.put(<span class="number">2</span>, <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">2</span>, <span class="string">&quot;Bella&quot;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="number">20</span>));</span><br><span class="line">        <span class="built_in">this</span>.map.put(<span class="number">3</span>, <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">3</span>, <span class="string">&quot;Cindy&quot;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="number">18</span>));</span><br><span class="line">        <span class="built_in">this</span>.map.put(<span class="number">4</span>, <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">4</span>, <span class="string">&quot;Diana&quot;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="number">20</span>));</span><br><span class="line">        <span class="built_in">this</span>.map.put(<span class="number">5</span>, <span class="keyword">new</span> <span class="title class_">User</span>(<span class="number">5</span>, <span class="string">&quot;Emily&quot;</span>, <span class="string">&#x27;F&#x27;</span>, <span class="number">18</span>));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;User&gt; <span class="title function_">getUserById</span><span class="params">(<span class="type">int</span> id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> Mono.justOrEmpty(<span class="built_in">this</span>.map.get(id));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Flux&lt;User&gt; <span class="title function_">getAllUsers</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> Flux.fromIterable(<span class="built_in">this</span>.map.values());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;Void&gt; <span class="title function_">saveUser</span><span class="params">(Mono&lt;User&gt; userMono)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> userMono.doOnNext(user -&gt; map.put(user.getId(), user))</span><br><span class="line">                .thenEmpty(Mono.empty());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserController</span> &#123;</span><br><span class="line">    UserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setUserService</span><span class="params">(UserService userService)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.userService = userService;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/user/&#123;id&#125;&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;User&gt; <span class="title function_">getUserById</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> <span class="type">int</span> id)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> userService.getUserById(id);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/users&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Flux&lt;User&gt; <span class="title function_">getAllUsers</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> userService.getAllUsers();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@PostMapping(&quot;/user&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;Void&gt; <span class="title function_">saveUser</span><span class="params">(User user)</span> &#123;</span><br><span class="line">        Mono&lt;User&gt; userMono = Mono.just(user);</span><br><span class="line">        <span class="keyword">return</span> userService.saveUser(userMono);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>Spring MVC 方式，同步阻塞的方式，基于 Spring MVC + Servlet + Tomcat；</li>
<li>Spring WebFlux 方式，异步非阻塞的方式，基于 Spring WebFlux + Reactor + Netty。</li>
</ul>
<h2 id="基于函数式编程模型"><a href="#基于函数式编程模型" class="headerlink" title="基于函数式编程模型"></a>基于函数式编程模型</h2><ul>
<li>使用函数式编程模型，需要自己初始化服务器</li>
<li>两个核心接口：RouterFunction（实现路由功能，请求转发给对应的 handler）和 HandlerFunction（处理请求生成响应的函数）。核心任务定义两个函数式接口的实现并且启动需要的服务器。</li>
<li>Spring WebFlux 的请求和响应不再是 ServletRequest 和 ServletResponse，而是 ServerRequest 和 ServerResponse。</li>
</ul>
<ol>
<li><p>把基于注解的复制一份，删去 controller 部分</p>
</li>
<li><p>创建 Handler</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserHandler</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> UserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">UserHandler</span><span class="params">(UserService userService)</span> &#123;</span><br><span class="line">        <span class="built_in">this</span>.userService = userService;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;ServerResponse&gt; <span class="title function_">getUserById</span><span class="params">(ServerRequest request)</span> &#123;</span><br><span class="line">        <span class="comment">// 获取 id 值</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">id</span> <span class="operator">=</span> Integer.parseInt(request.pathVariable(<span class="string">&quot;id&quot;</span>));</span><br><span class="line">        <span class="comment">// 空值处理</span></span><br><span class="line">        Mono&lt;ServerResponse&gt; notFound = ServerResponse.notFound().build();</span><br><span class="line">        <span class="comment">// 调用 service 得到数据</span></span><br><span class="line">        Mono&lt;User&gt; userMono = userService.getUserById(id);</span><br><span class="line">        <span class="comment">// 把 userMono 进行转换返回，使用 Reactor 操作符 flatMap</span></span><br><span class="line">        <span class="keyword">return</span> userMono.flatMap(user -&gt; ServerResponse.ok()</span><br><span class="line">                .contentType(MediaType.APPLICATION_JSON)</span><br><span class="line">                .body(BodyInserters.fromValue(user)))</span><br><span class="line">                .switchIfEmpty(notFound);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;ServerResponse&gt; <span class="title function_">getAllUsers</span><span class="params">()</span> &#123;</span><br><span class="line">        Flux&lt;User&gt; allUsers = userService.getAllUsers();</span><br><span class="line">        <span class="keyword">return</span> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)</span><br><span class="line">                .body(allUsers, User.class);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;ServerResponse&gt; <span class="title function_">saveUser</span><span class="params">(ServerRequest request)</span> &#123;</span><br><span class="line">        Mono&lt;User&gt; userMono = request.bodyToMono(User.class);</span><br><span class="line">        <span class="keyword">return</span> ServerResponse.ok().build(userService.saveUser(userMono));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>初始化服务器，编写 Router</p>
<ul>
<li>创建路由的方法</li>
<li>创建服务器完成适配</li>
<li>最终调用</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Server</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">Server</span> <span class="variable">server</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Server</span>();</span><br><span class="line">        server.createReactorServer();</span><br><span class="line">        System.out.println(<span class="string">&quot;enter to exit&quot;</span>);</span><br><span class="line">        System.in.read();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 1. 创建 Router 路由</span></span><br><span class="line">    <span class="keyword">public</span> RouterFunction&lt;ServerResponse&gt; <span class="title function_">routingFunction</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 创建 handler 对象</span></span><br><span class="line">        <span class="type">UserService</span> <span class="variable">userService</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UserServiceImpl</span>();</span><br><span class="line">        <span class="type">UserHandler</span> <span class="variable">userHandler</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UserHandler</span>(userService);</span><br><span class="line">        <span class="comment">// 设置路由</span></span><br><span class="line">        <span class="keyword">return</span> RouterFunctions.route(GET(<span class="string">&quot;/user/&#123;id&#125;&quot;</span>).and(accept(MediaType.APPLICATION_JSON)), userHandler::getUserById)</span><br><span class="line">                .andRoute(GET(<span class="string">&quot;/users&quot;</span>).and(accept(MediaType.APPLICATION_JSON)),</span><br><span class="line">                        userHandler::getAllUsers);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2. 创建服务器完成适配</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">createReactorServer</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 路由和 handler 适配</span></span><br><span class="line">        RouterFunction&lt;ServerResponse&gt; route = routingFunction();</span><br><span class="line">        <span class="type">HttpHandler</span> <span class="variable">httpHandler</span> <span class="operator">=</span> toHttpHandler(route);</span><br><span class="line">        <span class="type">ReactorHttpHandlerAdapter</span> <span class="variable">handlerAdapter</span> <span class="operator">=</span></span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">ReactorHttpHandlerAdapter</span>(httpHandler);</span><br><span class="line">        <span class="comment">// 创建服务器</span></span><br><span class="line">        <span class="type">HttpServer</span> <span class="variable">httpServer</span> <span class="operator">=</span> HttpServer.create();</span><br><span class="line">        httpServer.handle(handlerAdapter).bindNow();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用 WebClient 调用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Client</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">WebClient</span> <span class="variable">webClient</span> <span class="operator">=</span> WebClient.create(<span class="string">&quot;http://localhost:8235&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> webClient.get().uri(<span class="string">&quot;/user/&#123;id&#125;&quot;</span>, <span class="number">1</span>)</span><br><span class="line">                .accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class)</span><br><span class="line">                .block();</span><br><span class="line">        System.out.println(user);</span><br><span class="line"></span><br><span class="line">        Flux&lt;User&gt; users = webClient.get().uri(<span class="string">&quot;/users&quot;</span>)</span><br><span class="line">                .accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);</span><br><span class="line">        users.map(User::toString).buffer().doOnNext(System.out::println).blockFirst();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<hr>
<h1 id="课程总结"><a href="#课程总结" class="headerlink" title="课程总结"></a>课程总结</h1><ol>
<li><p>Spring 框架概述</p>
<p>轻量级开源 JavaEE 框架，核心 IoC 和 AOP</p>
</li>
<li><p>IoC 容器</p>
<ol>
<li>IoC 底层原理（工厂、反射等）</li>
<li>IoC 接口（BeanFactory）</li>
<li>IoC 操作 Bean 管理（基于 xml）</li>
<li>IoC 操作 Bean 管理（基于注解）</li>
</ol>
</li>
<li><p>AOP</p>
<ol>
<li>AOP 底层原理：动态代理，有接口（JDK 动态代理），没有接口（CGLIB 动态代理）</li>
<li>术语：切入点、增强（通知）、切面</li>
<li>基于 AspectJ 实现 AOP 操作</li>
</ol>
</li>
<li><p>JdbcTemplate</p>
<ol>
<li>使用 JdbcTemplate 实现 CRUD 操作</li>
<li>使用 JdbcTemplate 实现批量操作</li>
</ol>
</li>
<li><p>事务管理</p>
<ol>
<li>事务概念</li>
<li>重要概念（传播行为、隔离级别）</li>
<li>基于注解实现声明式事务管理</li>
<li>完全注解方式</li>
</ol>
</li>
<li><p>Spring 5 新特性</p>
<ol>
<li>整合日志框架</li>
<li><code>@Nullable</code> 注解</li>
<li>函数式注册对象</li>
<li>整合 JUnit 5 单元测试框架</li>
<li>Spring WebFlux</li>
</ol>
</li>
</ol>

    </div>

    
    
    
        <div class="reward-container">
  <div>曾梦想仗剑走天涯，后来没钱就没去</div>
  <button onclick="var qr = document.getElementById('qr'); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';">
    打赏
  </button>
  <div id="qr" style="display: none;">
      
      <div style="display: inline-block;">
        <img src="/images/wechatpay.png" alt="江南笑书生 微信支付">
        <p>微信支付</p>
      </div>
      
      <div style="display: inline-block;">
        <img src="/images/alipay.jpg" alt="江南笑书生 支付宝">
        <p>支付宝</p>
      </div>

  </div>
</div>

        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>江南笑书生
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="http://www.jnxss.top/2021/01/28/Spring-5-%E7%AC%94%E8%AE%B0/" title="Spring 5 笔记">http://www.jnxss.top/2021/01/28/Spring-5-笔记/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">
          
          <div class="post-tags">
              <a href="/tags/Spring/" rel="tag"><i class="fa fa-tag"></i> Spring</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2021/01/10/Spring-Boot-%E6%95%B4%E5%90%88-MyBatis/" rel="prev" title="Spring Boot 整合 MyBatis">
      <i class="fa fa-chevron-left"></i> Spring Boot 整合 MyBatis
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/04/26/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86/" rel="next" title="二叉树的遍历">
      二叉树的遍历 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E8%AF%BE%E7%A8%8B%E5%86%85%E5%AE%B9%E4%BB%8B%E7%BB%8D"><span class="nav-number">1.</span> <span class="nav-text">课程内容介绍</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Spring-%E6%A1%86%E6%9E%B6%E6%A6%82%E8%BF%B0"><span class="nav-number">2.</span> <span class="nav-text">Spring 框架概述</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#IoC"><span class="nav-number">3.</span> <span class="nav-text">IoC</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A6%82%E5%BF%B5%E5%92%8C%E5%8E%9F%E7%90%86"><span class="nav-number">3.1.</span> <span class="nav-text">概念和原理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8E%A5%E5%8F%A3"><span class="nav-number">3.2.</span> <span class="nav-text">接口</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#IoC-%E6%93%8D%E4%BD%9C-Bean-%E7%AE%A1%E7%90%86"><span class="nav-number">3.3.</span> <span class="nav-text">IoC 操作 Bean 管理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E-xml-%E6%96%B9%E5%BC%8F"><span class="nav-number">3.3.1.</span> <span class="nav-text">基于 xml 方式</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E-xml-%E6%96%B9%E5%BC%8F%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1"><span class="nav-number">3.3.1.1.</span> <span class="nav-text">基于 xml 方式创建对象</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E-xml-%E6%96%B9%E5%BC%8F%E6%B3%A8%E5%85%A5%E5%B1%9E%E6%80%A7"><span class="nav-number">3.3.1.2.</span> <span class="nav-text">基于 xml 方式注入属性</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#xml-%E6%B3%A8%E5%85%A5%E5%85%B6%E4%BB%96%E7%B1%BB%E5%9E%8B"><span class="nav-number">3.3.1.2.1.</span> <span class="nav-text">xml 注入其他类型</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#xml-%E6%B3%A8%E5%85%A5%E9%9B%86%E5%90%88%E5%B1%9E%E6%80%A7"><span class="nav-number">3.3.1.2.2.</span> <span class="nav-text">xml 注入集合属性</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#FactoryBean"><span class="nav-number">3.3.2.</span> <span class="nav-text">FactoryBean</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Bean-%E4%BD%9C%E7%94%A8%E5%9F%9F"><span class="nav-number">3.3.3.</span> <span class="nav-text">Bean 作用域</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Bean-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="nav-number">3.3.4.</span> <span class="nav-text">Bean 生命周期</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#xml-%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D"><span class="nav-number">3.3.5.</span> <span class="nav-text">xml 自动装配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A4%96%E9%83%A8%E5%B1%9E%E6%80%A7%E6%96%87%E4%BB%B6"><span class="nav-number">3.3.6.</span> <span class="nav-text">外部属性文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E6%96%B9%E5%BC%8F"><span class="nav-number">3.3.7.</span> <span class="nav-text">基于注解方式</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA-bean"><span class="nav-number">3.3.7.1.</span> <span class="nav-text">创建 bean</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B1%9E%E6%80%A7%E6%B3%A8%E5%85%A5"><span class="nav-number">3.3.7.2.</span> <span class="nav-text">属性注入</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#AOP"><span class="nav-number">4.</span> <span class="nav-text">AOP</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86"><span class="nav-number">4.1.</span> <span class="nav-text">底层原理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#JDK-%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86"><span class="nav-number">4.1.1.</span> <span class="nav-text">JDK 动态代理</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOP-%E6%9C%AF%E8%AF%AD"><span class="nav-number">4.2.</span> <span class="nav-text">AOP 术语</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOP-%E6%93%8D%E4%BD%9C"><span class="nav-number">4.3.</span> <span class="nav-text">AOP 操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BC%95%E5%85%A5%E4%BE%9D%E8%B5%96"><span class="nav-number">4.3.1.</span> <span class="nav-text">引入依赖</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%87%E5%85%A5%E7%82%B9%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="nav-number">4.3.2.</span> <span class="nav-text">切入点表达式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3"><span class="nav-number">4.3.3.</span> <span class="nav-text">基于注解</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E-xml-%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="nav-number">4.3.4.</span> <span class="nav-text">基于 xml 配置文件</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#JdbcTemplate"><span class="nav-number">5.</span> <span class="nav-text">JdbcTemplate</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE"><span class="nav-number">5.1.</span> <span class="nav-text">环境配置</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BC%95%E5%85%A5%E4%BE%9D%E8%B5%96-1"><span class="nav-number">5.1.1.</span> <span class="nav-text">引入依赖</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0"><span class="nav-number">5.1.2.</span> <span class="nav-text">配置数据库连接池</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE-JdbcTemplate"><span class="nav-number">5.1.3.</span> <span class="nav-text">配置 JdbcTemplate</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BC%96%E5%86%99%E7%B1%BB%E6%96%87%E4%BB%B6"><span class="nav-number">5.1.4.</span> <span class="nav-text">编写类文件</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E5%BA%93"><span class="nav-number">5.2.</span> <span class="nav-text">操作数据库</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A2%9E"><span class="nav-number">5.2.1.</span> <span class="nav-text">增</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%94%B9"><span class="nav-number">5.2.2.</span> <span class="nav-text">改</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%A0"><span class="nav-number">5.2.3.</span> <span class="nav-text">删</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5"><span class="nav-number">5.2.4.</span> <span class="nav-text">查</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%9F%90%E4%B8%AA%E5%80%BC"><span class="nav-number">5.2.4.1.</span> <span class="nav-text">某个值</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AF%B9%E8%B1%A1"><span class="nav-number">5.2.4.2.</span> <span class="nav-text">对象</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%9B%86%E5%90%88"><span class="nav-number">5.2.4.3.</span> <span class="nav-text">集合</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%89%B9%E9%87%8F%E6%93%8D%E4%BD%9C"><span class="nav-number">5.2.5.</span> <span class="nav-text">批量操作</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%B9%E9%87%8F%E6%B7%BB%E5%8A%A0"><span class="nav-number">5.2.5.1.</span> <span class="nav-text">批量添加</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%B9%E9%87%8F%E4%BF%AE%E6%94%B9"><span class="nav-number">5.2.5.2.</span> <span class="nav-text">批量修改</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%B9%E9%87%8F%E5%88%A0%E9%99%A4"><span class="nav-number">5.2.5.3.</span> <span class="nav-text">批量删除</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8B%E5%8A%A1"><span class="nav-number">6.</span> <span class="nav-text">事务</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A6%82%E5%BF%B5"><span class="nav-number">6.1.</span> <span class="nav-text">概念</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA"><span class="nav-number">6.2.</span> <span class="nav-text">环境搭建</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring-%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86"><span class="nav-number">6.3.</span> <span class="nav-text">Spring 事务管理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E7%9A%84%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86"><span class="nav-number">6.4.</span> <span class="nav-text">基于注解的声明式事务管理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E-XML-%E7%9A%84%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%AE%A1%E7%90%86"><span class="nav-number">6.5.</span> <span class="nav-text">基于 XML 的声明式事务管理</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%8C%E5%85%A8%E6%B3%A8%E8%A7%A3"><span class="nav-number">6.6.</span> <span class="nav-text">完全注解</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Spring-5-%E6%96%B0%E5%8A%9F%E8%83%BD"><span class="nav-number">7.</span> <span class="nav-text">Spring 5 新功能</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Spring-WebFlux"><span class="nav-number">8.</span> <span class="nav-text">Spring WebFlux</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Spring-WebFlux-%E4%BB%8B%E7%BB%8D"><span class="nav-number">8.1.</span> <span class="nav-text">Spring WebFlux 介绍</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E5%BC%82%E6%AD%A5%E9%9D%9E%E9%98%BB%E5%A1%9E%EF%BC%9F"><span class="nav-number">8.1.1.</span> <span class="nav-text">什么是异步非阻塞？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#WebFlux-%E7%89%B9%E7%82%B9"><span class="nav-number">8.1.2.</span> <span class="nav-text">WebFlux 特点</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AF%B9%E6%AF%94-Spring-MVC"><span class="nav-number">8.1.3.</span> <span class="nav-text">对比 Spring MVC</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B"><span class="nav-number">8.2.</span> <span class="nav-text">响应式编程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B%EF%BC%9F"><span class="nav-number">8.2.1.</span> <span class="nav-text">什么是响应式编程？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Java-8-%E5%8F%8A%E4%B9%8B%E5%89%8D%E7%89%88%E6%9C%AC"><span class="nav-number">8.2.2.</span> <span class="nav-text">Java 8 及之前版本</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B%EF%BC%88Reactor-%E5%AE%9E%E7%8E%B0%EF%BC%89"><span class="nav-number">8.2.3.</span> <span class="nav-text">响应式编程（Reactor 实现）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%A3%E7%A0%81%E6%BC%94%E7%A4%BA-Flux-%E5%92%8C-Mono"><span class="nav-number">8.2.4.</span> <span class="nav-text">代码演示 Flux 和 Mono</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="nav-number">8.2.5.</span> <span class="nav-text">操作符</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#WebFlux%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B%E5%92%8C%E6%A0%B8%E5%BF%83-API"><span class="nav-number">8.3.</span> <span class="nav-text">WebFlux执行流程和核心 API</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B"><span class="nav-number">8.4.</span> <span class="nav-text">基于注解编程模型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E4%BA%8E%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B%E6%A8%A1%E5%9E%8B"><span class="nav-number">8.5.</span> <span class="nav-text">基于函数式编程模型</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E8%AF%BE%E7%A8%8B%E6%80%BB%E7%BB%93"><span class="nav-number">9.</span> <span class="nav-text">课程总结</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="江南笑书生"
      src="/images/my-avatar.png">
  <p class="site-author-name" itemprop="name">江南笑书生</p>
  <div class="site-description" itemprop="description">心怀梦想，永远奋斗</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">17</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">13</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/5ME" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;5ME" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:cplasfyin@163.com" title="E-Mail → mailto:cplasfyin@163.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
      <span class="links-of-author-item">
        <a href="/images/qq.png" title="QQ → &#x2F;images&#x2F;qq.png"><i class="fab fa-qq fa-fw"></i>QQ</a>
      </span>
      <span class="links-of-author-item">
        <a href="/images/wechat.jpg" title="WeChat → &#x2F;images&#x2F;wechat.jpg"><i class="fab fa-weixin fa-fw"></i>WeChat</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        
  <div class="beian"><a href="https://beian.miit.gov.cn/" rel="noopener" target="_blank">豫ICP备2022008411号 </a>
      <img src="/images/%E5%A4%87%E6%A1%88%E5%9B%BE%E6%A0%87.png" style="display: inline-block;"><a href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=41062102410658" rel="noopener" target="_blank">豫公网安备 41062102410658号 </a>
  </div>

<div class="copyright">
  
  &copy; 2020 – 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heartbeat"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">江南笑书生</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">84k</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">1:16</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

        
<div class="busuanzi-count">
  <script data-pjax async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/pjax/pjax.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>

  <script>
var pjax = new Pjax({
  selectors: [
    'head title',
    '#page-configurations',
    '.content-wrap',
    '.post-toc-wrap',
    '.languages',
    '#pjax'
  ],
  switches: {
    '.post-toc-wrap': Pjax.switches.innerHTML
  },
  analytics: false,
  cacheBust: false,
  scrollTo : !CONFIG.bookmark.enable
});

window.addEventListener('pjax:success', () => {
  document.querySelectorAll('script[data-pjax], script#page-configurations, #pjax script').forEach(element => {
    var code = element.text || element.textContent || element.innerHTML || '';
    var parent = element.parentNode;
    parent.removeChild(element);
    var script = document.createElement('script');
    if (element.id) {
      script.id = element.id;
    }
    if (element.className) {
      script.className = element.className;
    }
    if (element.type) {
      script.type = element.type;
    }
    if (element.src) {
      script.src = element.src;
      // Force synchronous loading of peripheral JS.
      script.async = false;
    }
    if (element.dataset.pjax !== undefined) {
      script.dataset.pjax = '';
    }
    if (code !== '') {
      script.appendChild(document.createTextNode(code));
    }
    parent.appendChild(script);
  });
  NexT.boot.refresh();
  // Define Motion Sequence & Bootstrap Motion.
  if (CONFIG.motion.enable) {
    NexT.motion.integrator
      .init()
      .add(NexT.motion.middleWares.subMenu)
      .add(NexT.motion.middleWares.postList)
      .bootstrap();
  }
  NexT.utils.updateSidebarPosition();
});
</script>




  




  
<script src="//cdn.jsdelivr.net/npm/algoliasearch@4/dist/algoliasearch-lite.umd.js"></script>
<script src="//cdn.jsdelivr.net/npm/instantsearch.js@4/dist/instantsearch.production.min.js"></script>
<script src="/js/algolia-search.js"></script>














    <div id="pjax">
  

  

  

    </div>
</body>
</html>
